﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKArch.AreaStatistical.DataManager;
using YJKArch.Utils;

namespace YJKArch.AreaStatistical.SetRoomInfo
{
	public class RoomInfoCreator
	{
		public RoomInfoCreator(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
		}

		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public void Set()
		{
			try
			{
				this.ShowLabeledRoomInfo();
				this.SetRoomsInfo();
			}
			catch (Exception)
			{
				this.HideLabeledRoomInfo();
			}
			this.HideLabeledRoomInfo();
		}

		public void AutoSet()
		{
			List<RoomSettingInfo> list = new List<RoomSettingInfo>();
			List<RoomSettingInfo> list2 = new List<RoomSettingInfo>();
			List<RoomSettingInfo> list3 = new List<RoomSettingInfo>();
			List<RoomSettingInfo> list4 = new List<RoomSettingInfo>();
			RoomTypeSettingManager.ReadRoomTypeInfo(ref list, ref list2, ref list3, ref list4);
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			foreach (Room room in this.GetRooms(document, activeView.Id))
			{
				if (room != null)
				{
					if (this.GetTagsOfRoom(document, activeView.Id, room).Count == 0)
					{
						this.AddRoomTag(room);
					}
					RoomType roomType = RoomType.RT_Unknown;
					string name = room.Name;
					double coefficient = 1.0;
					bool isBalcony = false;
					int num = this.SearchRoomStyleByName(name, list);
					if (num != -1)
					{
						roomType = RoomType.RT_Hall;
						coefficient = list[num].m_Coefficient;
						isBalcony = list[num].m_IsBalcony;
					}
					else
					{
						num = this.SearchRoomStyleByName(name, list2);
						if (num != -1)
						{
							roomType = RoomType.RT_Room;
							coefficient = list2[num].m_Coefficient;
							isBalcony = list2[num].m_IsBalcony;
						}
						else
						{
							num = this.SearchRoomStyleByName(name, list3);
							if (num != -1)
							{
								roomType = RoomType.RT_Cell;
								coefficient = list3[num].m_Coefficient;
								isBalcony = list3[num].m_IsBalcony;
							}
							else
							{
								num = this.SearchRoomStyleByName(name, list4);
								if (num != -1)
								{
									roomType = RoomType.RT_Other;
									coefficient = list4[num].m_Coefficient;
									isBalcony = list4[num].m_IsBalcony;
								}
							}
						}
					}
					RoomSettingInfo roomSettingInfo = new RoomSettingInfo("", coefficient, isBalcony);
					this.SetInfos(room, roomType, roomSettingInfo);
					this.ShowSingleLabeledRoomInfo(room);
				}
			}
		}

		private int SearchRoomStyleByName(string name, List<RoomSettingInfo> roomStyleInfoList)
		{
			int result = -1;
			int num = 0;
			for (int i = 0; i < roomStyleInfoList.Count; i++)
			{
				RoomSettingInfo roomSettingInfo = roomStyleInfoList[i];
				int length = roomSettingInfo.m_Name.Length;
				if (name.IndexOf(roomSettingInfo.m_Name) != -1 && length > num)
				{
					result = i;
					num = length;
				}
			}
			return result;
		}

		private void AddRoomTag(Room room)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("new room tag");
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			XYZ point = (room.Location as LocationPoint).Point;
			UV point2 = new UV(point.X, point.Y);
			RevitVersionFuncs.NewRoomTag(document, room, point2, activeView);
			transaction.Commit();
		}

		private void ShowLabeledRoomInfo()
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			foreach (Room room in this.GetRooms(document, activeView.Id))
			{
				double num = 1.0;
				RoomType roomType = RoomType.RT_Other;
				bool flag = false;
				if (RoomInfoManager.ReadExtensibleStorageFromRoom(room, ref num, ref roomType, ref flag))
				{
					string text = "统计系数：" + num.ToString("f2");
					if (flag)
					{
						text += "(阳台)";
					}
					else
					{
						text += "(非阳台)";
					}
					XYZ xyz = (room.Location as LocationPoint).Point;
					xyz -= XYZ.BasisY * Common.MMToFeet(10.0);
					ElementId value = this.NewLabeledText(text, xyz, roomType);
					KeyValuePair<ElementId, ElementId> item = new KeyValuePair<ElementId, ElementId>(room.Id, value);
					this.m_Room2ndTempTextList.Add(item);
				}
			}
		}

		private void ShowSingleLabeledRoomInfo(Room room)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			int num = this.m_Room2ndTempTextList.FindIndex((KeyValuePair<ElementId, ElementId> value) => value.Key.IntegerValue == room.Id.IntegerValue);
			double num2 = 1.0;
			RoomType roomType = RoomType.RT_Other;
			bool flag = false;
			if (RoomInfoManager.ReadExtensibleStorageFromRoom(room, ref num2, ref roomType, ref flag))
			{
				string text = "统计系数：" + num2.ToString("f2");
				if (flag)
				{
					text += "(阳台)";
				}
				else
				{
					text += "(非阳台)";
				}
				XYZ xyz = (room.Location as LocationPoint).Point;
				xyz -= XYZ.BasisY * Common.MMToFeet(10.0);
				ElementId value3 = this.NewLabeledText(text, xyz, roomType);
				if (num != -1)
				{
					ElementId value2 = this.m_Room2ndTempTextList[num].Value;
					this.DeleteLable(value2);
					this.m_Room2ndTempTextList[num] = new KeyValuePair<ElementId, ElementId>(room.Id, value3);
					return;
				}
				KeyValuePair<ElementId, ElementId> item = new KeyValuePair<ElementId, ElementId>(room.Id, value3);
				this.m_Room2ndTempTextList.Add(item);
			}
		}

		private void HideLabeledRoomInfo()
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("hide label");
			foreach (KeyValuePair<ElementId, ElementId> keyValuePair in this.m_Room2ndTempTextList)
			{
				try
				{
					document.Delete(keyValuePair.Value);
				}
				catch (Exception)
				{
				}
			}
			transaction.Commit();
		}

		private void DeleteLable(ElementId lableId)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("hide label");
			try
			{
				document.Delete(lableId);
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			transaction.Commit();
		}

		private ElementId NewLabeledText(string info, XYZ pos, RoomType roomType)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("show label");
			XYZ basisX = XYZ.BasisX;
			XYZ basisY = XYZ.BasisY;
            TextAlignFlags textAlign = (TextAlignFlags)640;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			TextNote textNode = document.GetTextNode(activeView, pos, basisX, basisY, 1.0, textAlign, info);
			TextNoteType labelTextNoteType = this.GetLabelTextNoteType(roomType);
			if (labelTextNoteType != null)
			{
				textNode.TextNoteType = labelTextNoteType;
			}
			transaction.Commit();
			return textNode.Id;
		}

		private TextNoteType GetLabelTextNoteType(RoomType roomType)
		{
			string strB = "宋体 3mm";
			string text = "HY_RoomInfoLabel_Unknown";
			int num = 16711680;
			if (roomType == RoomType.RT_Hall)
			{
				num = 255;
				text = "HY_RoomInfoLabel_Hall";
			}
			else if (roomType == RoomType.RT_Room)
			{
				num = 255;
				text = "HY_RoomInfoLabel_Room";
			}
			else if (roomType == RoomType.RT_Cell)
			{
				num = 255;
				text = "HY_RoomInfoLabel_Cell";
			}
			else if (roomType == RoomType.RT_Other)
			{
				num = 255;
				text = "HY_RoomInfoLabel_Other";
			}
			TextNoteType textNoteType = null;
			TextNoteType textNoteType2 = null;
			TextNoteType textNoteType3 = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Revit.Application.ActiveUIDocument.Document);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType4 = element as TextNoteType;
				if (textNoteType4 != null)
				{
					if (textNoteType4.Name.CompareTo(text) == 0)
					{
						textNoteType = textNoteType4;
						break;
					}
					if (textNoteType2 == null && textNoteType4.Name.CompareTo(strB) == 0)
					{
						textNoteType2 = textNoteType4;
					}
					textNoteType3 = textNoteType4;
				}
			}
			if (textNoteType == null)
			{
				if (textNoteType3 == null)
				{
					return null;
				}
				if (textNoteType2 == null)
				{
					textNoteType2 = textNoteType3;
				}
				textNoteType = (textNoteType2.Duplicate(text) as TextNoteType);
				double num2 = Common.MMToFeet(3.5);
				textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(num2);
				string text2 = "FangSong_GB2312";
				textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).Set(text2);
				double num3 = 0.7;
				textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(num3);
				double num4 = Common.MMToFeet(8.0);
				textNoteType.get_Parameter(BuiltInParameter.TEXT_TAB_SIZE).Set(num4);
				textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).Set(num);
			}
			return textNoteType;
		}

		private void SetRoomsInfo()
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			SetRoomInfoForm setRoomInfoForm = new SetRoomInfoForm(this);
			setRoomInfoForm.Show(RoomInfoCreator._hWndRevit);
			int wMsg = 7;
			RoomInfoCreator.SendMessage(RoomInfoCreator._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			Room room = null;
			XYZ pos = null;
			try
			{
				while (this.SelelctRoom(ref room, ref pos))
				{
					if (room != null)
					{
						if (this.GetTagsOfRoom(document, activeView.Id, room).Count == 0)
						{
							this.NewRoomTag(room, document, activeView, pos);
						}
						this.SetInfos(room, setRoomInfoForm.TheRoomType, setRoomInfoForm.CurrentRoomSettingInfo);
						this.ShowSingleLabeledRoomInfo(room);
					}
				}
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				setRoomInfoForm.Close();
				return;
			}
			setRoomInfoForm.Close();
		}

		private bool SelelctRoom(ref Room room, ref XYZ pt)
		{
			if (!this.SelelctPosision(ref pt))
			{
				return false;
			}
			if (!this.SelectRoomByPoint(pt, ref room))
			{
				this.GetRoomByPoint(pt, ref room);
				return true;
			}
			return true;
		}

		private bool SelelctPosision(ref XYZ pt)
		{
			try
			{
				pt = this.m_Revit.Application.ActiveUIDocument.Selection.PickPoint("选取位置");
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private bool SelectRoomByPoint(XYZ pt, ref Room selectRoom)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			foreach (Room room in this.GetRooms(document, activeView.Id))
			{
				if (room.IsPointInRoom(pt))
				{
					selectRoom = room;
					return true;
				}
			}
			return false;
		}

		private bool GetRoomByPoint(XYZ pt, ref Room selectRoom)
		{
			Transaction transaction = new Transaction(this.m_Revit.Application.ActiveUIDocument.Document);
			transaction.Start("new rooms");
			int num = -1;
			try
			{
				List<Room> list = new List<Room>();
				Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
				Level genLevel = this.m_Revit.Application.ActiveUIDocument.ActiveView.GenLevel;
				foreach (object obj in document.get_PlanTopology(genLevel).Circuits)
				{
					PlanCircuit planCircuit = (PlanCircuit)obj;
					if (!planCircuit.IsRoomLocated)
					{
						Room item = document.Create.NewRoom(null, planCircuit);
						list.Add(item);
					}
				}
				for (int i = 0; i < list.Count; i++)
				{
					Room room = list[i];
					if (room.IsPointInRoom(pt))
					{
						selectRoom = room;
						num = i;
						break;
					}
				}
				for (int i = 0; i < list.Count; i++)
				{
					if (i != num)
					{
						document.Delete(list[i].Id);
					}
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
				return false;
			}
			transaction.Commit();
			return -1 != num;
		}

		private List<Room> GetRooms(Autodesk.Revit.DB.Document doc, ElementId viewId)
		{
			List<Room> list = new List<Room>();
            IEnumerable<Room> enumerable = from elem in new FilteredElementCollector(doc, viewId).WherePasses(new Autodesk.Revit.DB.Architecture.RoomFilter()).ToElements()
			let theRoom = elem as Room
			where theRoom != null
			select theRoom;
			if (enumerable != null)
			{
				foreach (Room item in enumerable)
				{
					list.Add(item);
				}
			}
			return list;
		}

		private List<ElementId> GetTagsOfRoom(Autodesk.Revit.DB.Document doc, ElementId viewId, Room room)
		{
			List<ElementId> list = new List<ElementId>();
			IEnumerable<RoomTag> enumerable = from elem in new FilteredElementCollector(doc, viewId).WherePasses(new RoomTagFilter()).ToElements()
			let roomTag = elem as RoomTag
			where roomTag != null && roomTag.Room != null
			select roomTag;
			if (enumerable != null)
			{
				foreach (RoomTag roomTag in enumerable)
				{
					Room room2 = roomTag.Room;
					if (room.Id.Compare(room2.Id) == 0)
					{
						list.Add(roomTag.Id);
					}
				}
			}
			return list;
		}

		private void NewRoomTag(Room room, Autodesk.Revit.DB.Document doc, Autodesk.Revit.DB.View acitveView, XYZ pos)
		{
			Transaction transaction = new Transaction(doc);
			transaction.Start("new room tag");
			try
			{
				RevitVersionFuncs.NewRoomTag(doc, room, new UV(pos.X, pos.Y), acitveView);
			}
			catch (Exception)
			{
				transaction.RollBack();
				return;
			}
			transaction.Commit();
		}

		private void SetInfos(Room room, RoomType roomType, RoomSettingInfo roomSettingInfo)
		{
			Transaction transaction = new Transaction(this.m_Revit.Application.ActiveUIDocument.Document);
			transaction.Start("set infos to room");
			try
			{
				if (roomSettingInfo.m_Name.CompareTo("") != 0)
				{
					room.get_Parameter(BuiltInParameter.ROOM_NAME).Set(roomSettingInfo.m_Name);
				}
				RoomInfoManager.WriteExtensibleStorageToRoom(room, roomSettingInfo.m_Coefficient, roomType, roomSettingInfo.m_IsBalcony);
			}
			catch (Exception)
			{
				transaction.RollBack();
				return;
			}
			transaction.Commit();
		}

		public static WindowHandle _hWndRevit;

		private ExternalCommandData m_Revit;

		private List<KeyValuePair<ElementId, ElementId>> m_Room2ndTempTextList = new List<KeyValuePair<ElementId, ElementId>>();
	}
}
